/*
 * @file gkt_widget.h
 */

#ifndef GKT_WIDGET_H
#define GKT_WIDGET_H

#include "gkt_types.h"
#include "gkt_widget_defines.h"

/* widget type */
enum {
#if defined(GKT_CONFIG_SCREEN_ENABLE) && GKT_CONFIG_SCREEN_ENABLE
	GKT_WIDGET_TYPE_LABEL,
	GKT_WIDGET_TYPE_IMAGE,
	GKT_WIDGET_TYPE_SELECT,	
#endif
	GKT_WIDGET_TYPE_INPUTBOX,
	GKT_WIDGET_TYPE_LIST,
	GKT_WIDGET_TYPE_MAX
};

/* widget event minor_type */
enum {
	/* widget event minor_type for widget manager */
	GKT_WIDGET_EVENT_INIT = 0,
	GKT_WIDGET_EVENT_UNINIT,
	GKT_WIDGET_EVENT_SHOW,
	GKT_WIDGET_EVENT_HIDE,
	GKT_WIDGET_EVENT_RESET,
	GKT_WIDGET_EVENT_SET_FOCUS,
	GKT_WIDGET_EVENT_LOST_FOCUS,
	GKT_WIDGET_EVENT_SET_ATTR,
	GKT_WIDGET_EVENT_SET_DATA,

	/* widget event minor type for user */
	GKT_WIDGET_EVENT_ITEM_FOCUS,
	GKT_WIDGET_EVENT_CLICK,
	GKT_WIDGET_EVENT_DATA_LENGTH,
	GKT_WIDGET_EVENT_DATA_EMPTY,
	GKT_WIDGET_EVENT_DATA_INSUFFICIENT,
	GKT_WIDGET_EVENT_DATA_FULL,
	GKT_WIDGET_EVENT_HEAD,
	GKT_WIDGET_EVENT_TAIL,

	GKT_WIDGET_EVENT_MAX
};

typedef uint16_t	gkt_widget_id_t;
typedef struct _gkt_widget_desc	gkt_widget_desc_s;
typedef struct _gkt_widget	gkt_widget_s;

typedef int (*gkt_widget_event_handler)(gkt_widget_s *widget, 
				uint32_t major_type, uint32_t minor_type, 
				uint32_t data);

#if defined(GKT_CONFIG_SCREEN_ENABLE) && GKT_CONFIG_SCREEN_ENABLE
/*
 * widget/widget_desc flags
 *  bit0 ~ bit15  : common flags (widget & widget_desc)
 *  bit16 ~ bit31 : widget dedicated flags
 */
#define GKT_WIDGET_F_ALIGN_LEFT		0
#define GKT_WIDGET_F_ALIGN_MIDDLE	1U
#define GKT_WIDGET_F_ALIGN_RIGHT	2U
#define GKT_WIDGET_F_ALIGN_HMASK	(3U)
#define GKT_WIDGET_F_ALIGN_TOP		(0 << 2)
#define GKT_WIDGET_F_ALIGN_CENTER	(1U << 2)
#define GKT_WIDGET_F_ALIGN_BOTTOM	(2U << 2)
#define GKT_WIDGET_F_ALIGN_VMASK	(3U << 2)
#define GKT_WIDGET_F_BORDER		(1U << 4)
#define GKT_WIDGET_F_SHOWABLE	(1U << 5)
#define GKT_WIDGET_F_FOCUSABLE	(1U << 6)
#define GKT_WIDGET_F_TITLE_MARK	(1U << 7)
#define GKT_WIDGET_F_KEY_VOICE_BYPASS	(1U << 8)
#define GKT_WIDGET_F_DESC_MASK	((1U << 16) - 1)

#define GKT_WIDGET_F_SHOW	(1U << 16)
#define GKT_WIDGET_F_FOCUS	(1U << 17)
#define GKT_WIDGET_F_ITEM_FOCUS	(1U << 18)

/* widget desc */
struct _gkt_widget_desc {
	uint16_t	flags;
	uint8_t type;
	uint8_t	font_size;

	gkt_rect_s	rect;

#if defined(GKT_CONFIG_SCREEN_ENABLE) && GKT_CONFIG_SCREEN_ENABLE \
	&& GKT_WIDGET_MULTIPLE_COLOR_ENABLE
	gkt_color_t fg_color;
#if GKT_WIDGET_BGCOLOR_VARIOUS
	gkt_color_t bg_color;
#endif
#endif

	uint32_t	attr;
};

#if GKT_WIDGET_MULTIPLE_COLOR_ENABLE
#if GKT_WIDGET_BGCOLOR_VARIOUS
#define GKT_WIDGET_DESC_COLOR_DEFINE(_fg_color, _bg_color)	\
	.fg_color	= _fg_color,	\
	.bg_color	= _bg_color,
#else
#define GKT_WIDGET_DESC_COLOR_DEFINE(_fg_color, _bg_color)	\
	.fg_color	= _fg_color,
#endif
#else
#define GKT_WIDGET_DESC_COLOR_DEFINE(_fg_color, _bg_color)
#endif

#define GKT_WIDGET_DESC(_TYPE, _flags, \
			_font_size, _fg_color, _bg_color,	\
			_x, _y, _width, _height, _attr)	\
	{	\
		.type	= GKT_WIDGET_TYPE_##_TYPE,	\
		.flags	= (uint16_t)(_flags),	\
		.font_size	= (uint8_t)(_font_size),	\
		GKT_WIDGET_DESC_COLOR_DEFINE(_fg_color, _bg_color)	\
		.rect	= {	\
			.x	= (uint16_t)_x,	\
			.y	= (uint16_t)_y,	\
			.width	= (uint16_t)_width,	\
			.height	= (uint16_t)_height,	\
		},	\
		.attr	= (uint32_t)(_attr),	\
	}

#define GKT_WIDGET_PAINT_EXCUTE	0x01
#define GKT_WIDGET_PAINT_UPDATE	0x02

#include "gkt_font.h"
#include "gkt_text.h"
#include "gkt_image.h"
#include "gkt_widget_label.h"
#include "gkt_widget_inputbox.h"
#include "gkt_widget_list.h"
#include "gkt_widget_image.h"
#include "gkt_widget_select.h"

#else
/*
 * widget/widget_desc flags
 *  bit0 ~ bit7  : common flags (widget & widget_desc)
 *  bit8 ~ bit15 : widget dedicated flags
 */
#define GKT_WIDGET_F_SHOWABLE	(1U << 0)
#define GKT_WIDGET_F_FOCUSABLE	(1U << 1)
#define GKT_WIDGET_F_KEY_VOICE_BYPASS	(1U << 4)
#define GKT_WIDGET_F_DESC_MASK	((1U << 16) - 1)

#define GKT_WIDGET_F_SHOW	(1U << 16)
#define GKT_WIDGET_F_FOCUS	(1U << 17)

struct _gkt_widget_desc {
	uint16_t	flags;
	uint8_t type;
	uint8_t	rfu;
	uint32_t	attr;
};

#define GKT_WIDGET_DESC(_TYPE, _flags, _attr)	\
	{	\
		.type	= GKT_WIDGET_TYPE_##_TYPE,	\
		.flags	= (uint16_t)(_flags),	\
		.rfu	= 0,	\
		.attr	= (uint32_t)(_attr),	\
	}

#include "gkt_widget_defines.h"
#include "gkt_widget_inputbox.h"
#include "gkt_widget_list.h"
#endif

/* widget */
struct _gkt_window;
struct _gkt_widget {
	uint32_t	flags;
	gkt_widget_id_t	id;

	const gkt_widget_desc_s	*desc;
	struct _gkt_window	*window;

#if defined(GKT_CONFIG_SCREEN_ENABLE) && GKT_CONFIG_SCREEN_ENABLE \
	&& GKT_WIDGET_MULTIPLE_COLOR_ENABLE
	gkt_color_t fg_color;
#if GKT_WIDGET_BGCOLOR_VARIOUS
	gkt_color_t bg_color;
#endif
#endif

	uint32_t	private_data;
};

int gkt_widget_event_dispatch(gkt_widget_s *widget, 
			uint32_t major_type, uint32_t minor_type, 
			uint32_t data);

gkt_widget_s *gkt_widget_by_id(gkt_widget_id_t widget_id);

void gkt_widget_set_showable_by_id(gkt_widget_id_t widget_id, 
			int showable);

void gkt_widget_update(gkt_widget_s *widget);
void gkt_widget_update_by_id(gkt_widget_id_t widget_id);

void gkt_widget_show(gkt_widget_s *widget, uint32_t update);
void gkt_widget_show_by_id(gkt_widget_id_t widget_id);
int gkt_widget_is_showed_by_id(gkt_widget_id_t widget_id);

void gkt_widget_hide(gkt_widget_s *widget);
void gkt_widget_hide_by_id(gkt_widget_id_t widget_id);

#if defined(GKT_CONFIG_SCREEN_ENABLE) && GKT_CONFIG_SCREEN_ENABLE
void gkt_widget_enable_item_focus_by_id(gkt_widget_id_t widget_id);
#else
#define gkt_widget_enable_item_focus_by_id(widget_id)	\
	do { gkt_unused(widget_id); } while (0)
#endif

void gkt_widget_set_focus_by_id(gkt_widget_id_t widget_id);
int gkt_widget_set_attr_by_id(gkt_widget_id_t widget_id, 
			uint32_t attr);
int gkt_widget_set_data_by_id(gkt_widget_id_t widget_id, uint32_t data);
void gkt_widget_reset_by_id(gkt_widget_id_t widget_id);

#if defined(GKT_CONFIG_SCREEN_ENABLE) && GKT_CONFIG_SCREEN_ENABLE \
	&& GKT_WIDGET_MULTIPLE_COLOR_ENABLE
void gkt_widget_set_color_by_id(gkt_widget_id_t widget_id, 
				gkt_color_t fg_color, gkt_color_t bg_color);

void gkt_widget_set_fg_color_by_id(gkt_widget_id_t widget_id, 
				gkt_color_t color);
void gkt_widget_set_bg_color_by_id(gkt_widget_id_t widget_id, 
				gkt_color_t color);
#else
#define gkt_widget_set_color_by_id(widget_id, fg_color, bg_color)
#define gkt_widget_set_fg_color_by_id(widget_id, color)
#define gkt_widget_set_bg_color_by_id(widget_id, color)
#endif

#endif	/* GKT_WIDGET_H */

